﻿using Common;
using ImClient.Properties;
using ImCommon;
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace ImClient {
    // 主窗口
    public partial class MainWindow: Form {
        private readonly Dictionary<string, ChatWindow> mChats; // 聊天窗口集合
        private readonly Client mClient;                        // 客户端

        /**
         * 构造方法。
         */
        public MainWindow() {
            // 初始化控件
            this.InitializeComponent();

            // 初始化成员
            mChats = new Dictionary<string, ChatWindow>();

            // 设置状态栏文字
            LabelFriendCount.Text = string.Format(Resources.IDS_FRIEND_COUNT, 0);

            // 创建客户端
            try {
                mClient = new Client(this);
            } catch (Exception) {
                string message = this.GetResultMessage(ResultCode.NETWORK_ERROR);
                MessageBox.Show(message, " ", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Application.Exit();
            }

            // 订阅事件
            mClient.OnChatS2C = new Client.ON_CHAT_S2C(OnChatS2C);
            mClient.OnFriendLogoff = new Client.ON_FRIEND_LOGOFF(OnFriendLogoff);
            mClient.OnFriendLogon = new Client.ON_FRIEND_LOGON(OnFriendLogon);
            mClient.OnGetAddFriendRequest = new Client.ON_GET_ADD_FRIEND_REQUEST(OnGetAddFriendRequest);
            mClient.OnGetAddFriendResult = new Client.ON_GET_ADD_FRIEND_RESULT(OnGetAddFriendResult);
            mClient.OnGetLogonResult = new Client.ON_GET_LOGON_RESULT(OnGetLogonResult);
            mClient.OnGetRegResult = new Client.ON_GET_REG_RESULT(OnGetRegResult);
        }

        /**
         * 添加所有好友到好友列表控件中。
         * @param result    登录结果
         */
        private void AddAllFriends(LogonResult result) {
            for (int i = 0; i < result.mFriendCount; i++) {
                this.AddOneFriend(result.mFriends[i].mUsername, result.mFriends[i].mIconIndex, result.mFriendsOnline[i]);
            }

            LabelFriendCount.Text = string.Format(Resources.IDS_FRIEND_COUNT, result.mFriendCount);
        }

        /**
         * 添加一个好友到好友列表控件中。
         * @param friendName    好友名
         * @param iconIndex     好友头像索引
         * @param isOnline      好友在线则为 true，否则为 false
         */
        private void AddOneFriend(string friendName, int iconIndex, bool isOnline) {
            if (iconIndex < 0) {
                return;
            }
            ListViewUsers.AddItem(friendName, iconIndex, isOnline);
        }

        /**
         * "添加好友"按钮的单击响应方法。
         * @param sender    事件发送者
         * @param e         事件相关信息
         */
        private void ButtonAddFriend_Click(object sender, EventArgs e) {
            // 显示输入窗口，让用户输入好友名
            string tipText = Resources.IDS_PLEASE_INPUT_USERNAME;
            string username = InputBox.GetStringValue(tipText, "");
            if (username == null || username.Equals("")) {
                return;
            }

            // 执行添加好友
            ResultCode resultCode = mClient.AddFriend(username);
            if (resultCode != ResultCode.SUCCEEDED) {
                string message = this.GetResultMessage(resultCode);
                MessageBox.Show(message, " ", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        
        /**
         * "离线"按钮的单击响应方法。
         * @param sender    事件发送者
         * @param e         事件相关信息
         */
        private void ButtonLogoff_Click(object sender, EventArgs e) {
            // 设置各种控件的状态
            this.ChangeState(false);

            // 清空各种列表
            ListViewUsers.Items.Clear();
            this.ClearChatWindow();

            // 发送离线请求
            mClient.Logoff();
        }

        /**
         * "登录"按钮的单击响应方法。
         * @param sender    事件发送者
         * @param e         事件相关信息
         */
        private void ButtonLogon_Click(object sender, EventArgs e) {
            // 显示登录窗口
            LogonWindow logonWindow = new LogonWindow();
            DialogResult result = logonWindow.ShowDialog();
            if (result == DialogResult.OK) {
                // 登录
                mClient.Logon(logonWindow.Username, logonWindow.Password);
            }
        }

        /**
         * "群发消息"按钮的单击响应方法。
         * @param sender    事件发送者
         * @param e         事件相关信息
         */
        private void ButtonMChat_Click(object sender, EventArgs e) {
            this.GetChatWindow(ImProtocol.MULTI_CHAT).Visible = true;
        }

        /**
         * "注册"按钮的单击响应方法。
         * @param sender    事件发送者
         * @param e         事件相关信息
         */
        private void ButtonReg_Click(object sender, EventArgs e) {
            // 显示注册窗口
            RegWindow regWindow = new RegWindow();
            DialogResult result = regWindow.ShowDialog();
            if (result == DialogResult.OK) {
                // 注册
                mClient.Reg(regWindow.Username, regWindow.Password, regWindow.IconIndex);
            }
        }

        /**
         * 改变界面状态。
         * @param isLogon   已登录则为 true，否则为 false
         */
        private void ChangeState(bool isLogon) {
            ButtonLogon.Enabled = !isLogon;
            ButtonReg.Enabled = !isLogon;
            ButtonAddFriend.Enabled = isLogon;
            ButtonMChat.Enabled = isLogon;
            ButtonLogoff.Enabled = isLogon;

            if (isLogon) {
                LabelStatus.Text = Resources.IDS_STATUS_LOGON;
            } else {
                LabelStatus.Text = Resources.IDS_STATUS_LOGOFF;
            }
            LabelFriendCount.Text = string.Format(Resources.IDS_FRIEND_COUNT, 0);
        }

        /**
         * 清除所有聊天窗口。
         */
        private void ClearChatWindow() {
            foreach (ChatWindow window in mChats.Values) {
                window.Dispose();
            }
            mChats.Clear();
        }

        /**
         * 获取指定好友名对应的聊天窗口。
         * @param friendName 好友名
         * @return 好友名对应的聊天窗口
         */
        private ChatWindow GetChatWindow(string friendName) {
            // 查找用户名对应的聊天窗口
            ChatWindow window;
            bool found = mChats.TryGetValue(friendName, out window);
            if (!found) {
                // 未找到，则新建一个
                window = new ChatWindow(this, friendName);
                window.OnChatC2S = new ChatWindow.ON_CHAT_C2S(OnChatC2S);
                mChats.Add(friendName, window);
            }

            return window;
        }

        /**
         * 获取结果信息。
         * @param resultCode    结果码
         * @return 结果信息
         */
        private string GetResultMessage(ResultCode resultCode) {
            switch (resultCode) {
                case ResultCode.ADD_FRIEND_ALLOW:
                    return Resources.IDS_ADD_FRIEND_ALLOW;
                case ResultCode.ADD_FRIEND_NOT_ALLOW:
                    return Resources.IDS_ADD_FRIEND_NOT_ALLOW;
                case ResultCode.ALREADY_BE_FRIENDS:
                    return Resources.IDS_ALREADY_BE_FRIENDS;
                case ResultCode.FRIEND_NAME_EQUAL_SELF_NAME:
                    return Resources.IDS_FRIEND_NAME_EQUAL_SELF_NAME;
                case ResultCode.NETWORK_ERROR:
                    return Resources.IDS_NETWORK_ERROR;
                case ResultCode.PASSWORD_WRONG:
                    return Resources.IDS_PASSWORD_WRONG;
                case ResultCode.REG_SUCCEEDED:
                    return Resources.IDS_REG_SUCCEEDED;
                case ResultCode.TOO_MANY_FRIENDS:
                    return Resources.IDS_TOO_MANY_FRIENDS;
                case ResultCode.USER_ALREADY_LOGON:
                    return Resources.IDS_USER_ALREADY_LOGON;
                case ResultCode.USER_EXISTS:
                    return Resources.IDS_USER_EXISTS;
                case ResultCode.USER_NOT_FOUND:
                    return Resources.IDS_USER_NOT_FOUND;
            }

            return "";
        }

        /**
         * 双击好友列表控件的响应方法。
         * @param sender    事件发送者
         * @param e         事件相关信息
         */
        private void ListFriends_DoubleClick(object sender, EventArgs e) {
            string friendName = ListViewUsers.SelectedItems[0].Text;
            this.GetChatWindow(friendName).Visible = true;
        }

        /**
         * 窗口关闭后事件的响应方法。
         * @param sender    事件发送者
         * @param e         事件相关信息
         */
        private void MainWindow_FormClosed(object sender, FormClosedEventArgs e) {
            // 关闭客户端
            if (mClient != null) {
                mClient.Close();
            }
        }

        /**
         * 聊天事件的响应方法（客户端到服务器）。
         * @param chatInfo  聊天信息
         */
        private void OnChatC2S(ChatInfo chatInfo) {
            mClient.Chat(chatInfo);
        }

        /**
         * 聊天事件的响应方法（服务器到客户端）。
         * @param chatInfo  聊天信息
         */
        private void OnChatS2C(ChatInfo chatInfo) {
            ChatWindow chatWindow;
            if (chatInfo.mDstUsername == ImProtocol.MULTI_CHAT) {
                chatWindow = this.GetChatWindow(ImProtocol.MULTI_CHAT);
            } else {
                chatWindow = this.GetChatWindow(chatInfo.mSrcUsername);
            }
            chatWindow.SetContent(chatInfo);
            chatWindow.Visible = true;
        }

        /**
         * 好友离线事件的响应方法。
         * @param request    离线请求
         */
        private void OnFriendLogoff(LogoffRequest request) {
            ListViewUsers.ChangeItemColor(request.mUsername, false);
        }

        /**
         * 好友登录事件的响应方法。
         * @param friendLogon    好友登录信息
         */
        private void OnFriendLogon(FriendLogon friendLogon) {
            ListViewUsers.ChangeItemColor(friendLogon.mUsername, true);
        }

        /**
         * 得到添加好友请求事件的响应方法。
         * @param request   添加好友请求
         */
        private void OnGetAddFriendRequest(AddFriendRequest request) {
            string message = request.mSrcUsername + Resources.IDS_CONFIRM_ADD_FRIEND;
            DialogResult clickedButton = MessageBox.Show(message, " ", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            bool allow = clickedButton == DialogResult.Yes;
            mClient.AllowAddFriend(allow, request);
            if (allow) {
                this.AddOneFriend(request.mSrcUsername, request.mSrcIconIndex, true);
                LabelFriendCount.Text = string.Format(Resources.IDS_FRIEND_COUNT, mClient.FriendCount);
            }
        }

        /**
         * 得到添加好友结果事件的响应方法。
         * @param result    添加好友结果
         */
        private void OnGetAddFriendResult(AddFriendResult result) {
            string message = this.GetResultMessage(result.mResultCode);
            if (result.mResultCode == ResultCode.ADD_FRIEND_ALLOW) {
                this.AddOneFriend(result.mDstUsername, result.mDstIconIndex, true);
                LabelFriendCount.Text = string.Format(Resources.IDS_FRIEND_COUNT, mClient.FriendCount);
                message = string.Format(message, result.mDstUsername);
                MessageBox.Show(message, " ", MessageBoxButtons.OK, MessageBoxIcon.Information);
            } else if (result.mResultCode == ResultCode.ALREADY_BE_FRIENDS || 
                result.mResultCode == ResultCode.ADD_FRIEND_NOT_ALLOW ||
                result.mResultCode == ResultCode.USER_NOT_FOUND) {
                message = result.mDstUsername + message;
                MessageBox.Show(message, " ", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        /**
         * 得到登录结果事件的响应方法。
         * @param result    登录结果
         */
        private void OnGetLogonResult(LogonResult result) {
            if (result.mResultCode == ResultCode.LOGON_SUCCEEDED) {
                this.ChangeState(true);
                this.AddAllFriends(result);
            } else {
                string message = this.GetResultMessage(result.mResultCode);
                MessageBox.Show(message, " ", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /**
         * 得到注册结果事件的响应方法。
         * @param result    注册结果
         */
        private void OnGetRegResult(RegResult result) {
            string message = this.GetResultMessage(result.mResultCode);
            if (result.mResultCode == ResultCode.REG_SUCCEEDED) {
                this.ChangeState(true);
                MessageBox.Show(message, " ", MessageBoxButtons.OK, MessageBoxIcon.Information);
            } else {
                MessageBox.Show(message, " ", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}
